#include <cstdlib>
#include <cmath>
#include <cstdio>
#include "data.h"

data::data (uint32 buff_size, char * filename)
{
	this->buff_size = buff_size;
	data_buff = (data_block *) calloc (this->buff_size, sizeof (data_block));
	// Starting at beginning of buffer
	buff_index = 0;
	t = 0;
	// This constructor has an output file too
	out = fopen (filename, "w");
	if (out == NULL)
		printf ("Error opening output file in data constructor.\n");
}

data::data (uint32 buff_size)
{
	this->buff_size = buff_size;
	t = 0;
	data_buff = (data_block *) calloc (this->buff_size, sizeof (data_block));
	// Starting at beginning of buffer
	buff_index = 0;
}

data::~data ()
{
	free (data_buff);
	if (out != NULL)
		fclose (out);
}

int data::count_M (uint8 * lat, uint32 n_sites)
{
	static uint32 i;
	int M = 0;

	for (i=0; i<n_sites; ++i)
		M += lat[i] ? 1 : -1;

	return M;
}

void data::output (FILE * file, data_block * data_buff, uint32 buff_size)
{
	static uint32 i;
	static char output_data [150];

	for (i=0; i<buff_size; ++i)
	{
		sprintf (output_data, "%.3f\t%.3f\t%e\t%e\t%u\n",
			data_buff[i].h, 
			data_buff[i].tau, 
			data_buff[i].m, 
			data_buff[i].m2,
			data_buff[i].t);

		if (file != NULL)
			fputs (output_data, file);
		else
			printf ("Error with output file\n");
	}
}

int data::data_step (uint8 * lat, uint32 n_sites, double tau, double h)
{
	data_buff[buff_index].tau = tau;
	data_buff[buff_index].h   = h;
	data_buff[buff_index].m   = (double)count_M (lat, n_sites)/n_sites;
	data_buff[buff_index].m2  = data_buff[buff_index].m*data_buff[buff_index].m;
	data_buff[buff_index].t   = t;

	if (buff_index >= buff_size - 1)
	{
		// Buffer is full, write it and start over.
		output (out, data_buff, buff_size);

		buff_index = 0;
	}
	else
		++buff_index;

	// Stop when net magnetization is aligned with the field -- when this is
	// the case, nucleation has certainly ocurred. 
	if ( data_buff[buff_index].m*h > 0 )
	{
		//output (out, data_buff, buff_index);	
		return 1;
	}

	++t;
	return 0;
}
